/*
 * Copyright (c) 2018-2999 湖南洛云网络科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.multishop.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.event.ProcessGroupProdPriceEvent;
import com.yami.shop.bean.event.ProcessSeckillProdPriceEvent;
import com.yami.shop.bean.event.ProdChangeEvent;
import com.yami.shop.bean.event.ProdChangeStatusEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.bean.param.ProductExportParam;
import com.yami.shop.bean.param.ProductParam;
import com.yami.shop.bean.param.RetailProdParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.i18n.LanguageEnum;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.dao.SkuRetailMapper;
import com.yami.shop.groupbuy.comment.api.dto.ApiGroupActivityDto;
import com.yami.shop.groupbuy.comment.enums.ActivityStatusEnum;
import com.yami.shop.groupbuy.comment.model.GroupProd;
import com.yami.shop.groupbuy.comment.service.GroupActivityService;
import com.yami.shop.groupbuy.comment.service.GroupProdService;
import com.yami.shop.security.multishop.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 商品列表、商品发布controller
 *
 * @author lgh
 */
@Controller
@RequestMapping("/prod/prod")
public class ProductController {

    @Autowired
    private ProductService productService;

    @Autowired
    private MapperFacade mapperFacade;

    @Autowired
    private SkuService skuService;

    @Autowired
    private BasketService basketService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private OfflineHandleEventService offlineHandleEventService;

    @Autowired
    private ShopDetailService shopDetailService;

    @Autowired
    private ProdLangService prodLangService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RetailProdService retailProdService;

    @Autowired
    private SkuRetailMapper skuRetailMapper;

    @Autowired
    private GroupProdService groupProdService;

    @Autowired
    private GroupActivityService groupActivityService;

    /**
     * 分页获取商品信息
     */
    @GetMapping("/page")
    public ResponseEntity<IPage<Product>> page(ProductParam product, PageParam<Product> page) {
        product.setLang(I18nMessage.getDbLang());
        product.setShopId(SecurityUtils.getShopUser().getShopId());
        IPage<Product> products = productService.pageByLang(page,product);
        processActivityProdPrice(products.getRecords());
        return ResponseEntity.ok(products);
    }


    /**
     * 处理下活动商品的价格
     * @param products
     */
    private void processActivityProdPrice(List<Product> products) {
        Map<Integer, List<Product>> prodMap = products.stream().collect(Collectors.groupingBy(Product::getProdType));
        if (prodMap.containsKey(ProdType.PROD_TYPE_SECKILL.value())){
            applicationContext.publishEvent(new ProcessSeckillProdPriceEvent(prodMap.get(ProdType.PROD_TYPE_SECKILL.value())));
        }

        if (prodMap.containsKey(ProdType.PROD_TYPE_GROUP.value())){
            applicationContext.publishEvent(new ProcessGroupProdPriceEvent(prodMap.get(ProdType.PROD_TYPE_GROUP.value())));
        }
    }

    /**
     * 分页获取商品信息
     */
    @GetMapping("/listProdByIdsAndType")
    public ResponseEntity<List<Product>> listProdByIdsAndType(ProductParam product) {
        product.setLang(I18nMessage.getDbLang());
        product.setShopId(SecurityUtils.getShopUser().getShopId());
        List<Product> products = productService.listProdByIdsAndType(product);
        return ResponseEntity.ok(products);
    }

    /**
     * 分页获取上架的商品信息
     */
    @GetMapping("/pageOnLineProd")
    public ResponseEntity<IPage<Product>> pageOnLineProd(ProductParam product, PageParam<Product> page) {
        product.setShopId(SecurityUtils.getShopUser().getShopId());
        IPage<Product> products = productService.pageProducts(page,product);
        return ResponseEntity.ok(products);
    }

    /**
     * 获取信息
     */
    @GetMapping("/info/{prodId}")
    public ResponseEntity<Product> info(@PathVariable("prodId") Long prodId) {
        Product prod = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
        if (!Objects.equals(prod.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }
//        Brand brand = brandService.getById(prod.getBrandId());
//        if (Objects.nonNull(brand)){
//            prod.setBrand(brand);
//        }
        List<Sku> skuList = skuService.listByProdId(prodId, I18nMessage.getLang());
        for (Sku sku : skuList) {
            for (SkuLang skuLang : sku.getSkuLangList()) {
                // sku 规格国际化，因为不是关联表的形式，所以多语言一起返回数据
                if(Objects.equals(skuLang.getLang(),1)){
                    String propertiesEn = skuLang.getProperties();
                    String skuName = skuLang.getSkuName();
                    sku.setPropertiesEn(StrUtil.isNotBlank(propertiesEn)?propertiesEn:sku.getProperties());
                    sku.setSkuNameEn(StrUtil.isNotBlank(skuName)?skuName:sku.getSkuName());
                }
                // 适配一些数据
                if (StrUtil.isBlank(sku.getPropertiesEn())) {
                    sku.setPropertiesEn(sku.getProperties());
                }
            }
        }
        prod.setSkuList(skuList);
        // 获取语言列表
        List<ProdLang> prodLangList = prodLangService.list(new LambdaQueryWrapper<ProdLang>().eq(ProdLang::getProdId, prodId));
        prod.setProdLangList(prodLangList);
        // 是否是组合商品
        if (Objects.equals(1,prod.getIsCompose())) {
            for (Sku sku : skuList) {
                List<RetailProdParam> skuSingleProds = retailProdService.getBySkuId(sku.getSkuId());
                if (CollectionUtils.isNotEmpty(skuSingleProds)) {
                    sku.setSkuSingleProds(skuSingleProds);
                }
            }
        }
        return ResponseEntity.ok(prod);
    }

    /**
     * 保存
     */
    @PostMapping
    @PreAuthorize("@pms.hasPermission('prod:prod:save')")
    public ResponseEntity<String> save(@Valid @RequestBody ProductParam productParam) {
        checkParam(productParam);
        Long shopId = SecurityUtils.getShopUser().getShopId();
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            // 店铺处于违规下线中，不能修改商品，请联系管理员后重试
            throw new YamiShopBindException("yami.product.shop.offline");
        }
        Product product = mapperFacade.map(productParam, Product.class);
        product.setStatus(1);
        product.setDeliveryMode(Json.toJsonString(productParam.getDeliveryModeVo()));
        product.setShopId(shopId);
        product.setUpdateTime(new Date());
        product.setPutawayTime(new Date());
        product.setCreateTime(new Date());
        product.setVersion(0);
        // 商品销量设置为0
        product.setSoldNum(0);
        product.setProdType(ProdType.PROD_TYPE_NORMAL.value());
        product.setActivityId(0L);
        productService.saveProduct(product,productParam);
        return ResponseEntity.ok().build();
    }

    /**
     * 修改
     */
    @PutMapping
    @PreAuthorize("@pms.hasPermission('prod:prod:update')")
    public ResponseEntity<String> update(@Valid @RequestBody ProductParam productParam) {
        checkParam(productParam);
        Product dbProduct = productService.getProductByProdId(productParam.getProdId(), I18nMessage.getDbLang());
        if(Objects.equals(dbProduct.getStatus(), ProdStatusEnums.DELETE.getValue())) {
            // 产品已被删除
            throw new YamiShopBindException("yami.product.service.delete");
        }
        if (!Objects.equals(dbProduct.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }
        Long shopId = SecurityUtils.getShopUser().getShopId();
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            // 店铺处于违规下线中，不能修改商品，请联系管理员后重试
            throw new YamiShopBindException("yami.product.shop.offline");
        }

        List<String> userIds = basketService.listUserIdByProdId(productParam.getProdId());


        List<Sku> dbSkus = skuService.listByProdId(dbProduct.getProdId(), I18nMessage.getDbLang());

        dbProduct.setSkuList(dbSkus);
        productParam.setProdType(null);
        productService.updateProduct(productParam, dbProduct);


        // 清除缓存
        productService.removeProdCacheByProdId(productParam.getProdId(), LanguageEnum.LANGUAGE_EN.getLang());
        productService.removeProdCacheByProdId(productParam.getProdId(),LanguageEnum.LANGUAGE_ZH_CN.getLang());
        for (String userId : userIds) {
            basketService.removeShopCartItemsCacheByUserId(userId,LanguageEnum.LANGUAGE_ZH_CN.getLang());
            basketService.removeShopCartItemsCacheByUserId(userId,LanguageEnum.LANGUAGE_EN.getLang());
        }
        for (Sku sku : dbSkus) {
            skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(), LanguageEnum.LANGUAGE_ZH_CN.getLang());
            skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(),LanguageEnum.LANGUAGE_EN.getLang());
        }
        return ResponseEntity.ok().build();
    }

    /**
     * 删除
     */
    @DeleteMapping("/{prodId}")
    @PreAuthorize("@pms.hasPermission('prod:prod:delete')")
    public ResponseEntity<Void> delete(@PathVariable("prodId") Long prodId) {
        Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
        if (!Objects.equals(dbProduct.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }
        List<Sku> dbSkus = skuService.listByProdId(dbProduct.getProdId(), I18nMessage.getDbLang());
        // 删除商品
        productService.removeProductByProdId(prodId);

        for (Sku sku : dbSkus) {
            skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(), LanguageEnum.LANGUAGE_ZH_CN.getLang());
            skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(),LanguageEnum.LANGUAGE_EN.getLang());
        }

        List<String> userIds = basketService.listUserIdByProdId(prodId);
        //清除缓存
        productService.removeProdCacheByProdId(prodId, LanguageEnum.LANGUAGE_EN.getLang());
        productService.removeProdCacheByProdId(prodId,LanguageEnum.LANGUAGE_ZH_CN.getLang());
        for (String userId : userIds) {
            basketService.removeShopCartItemsCacheByUserId(userId,LanguageEnum.LANGUAGE_ZH_CN.getLang());
            basketService.removeShopCartItemsCacheByUserId(userId,LanguageEnum.LANGUAGE_EN.getLang());
        }
        for (Sku sku : dbSkus) {
            skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(),LanguageEnum.LANGUAGE_ZH_CN.getLang());
            skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(),LanguageEnum.LANGUAGE_EN.getLang());
        }
        return ResponseEntity.ok().build();
    }


    /**
     * 更新商品状态
     */
    @PutMapping("/prodStatus")
    @PreAuthorize("@pms.hasPermission('prod:prod:status')")
    public ResponseEntity<Void> shopStatus(@RequestBody ProductParam productParam) {
        Long prodId = productParam.getProdId();
        Integer prodStatus = productParam.getStatus();
        Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
        if (!Objects.equals(dbProduct.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }
        if (!(Objects.equals(dbProduct.getStatus(), ProdStatusEnums.NORMAL.getValue())
                || Objects.equals(dbProduct.getStatus(), ProdStatusEnums.SHOP_OFFLINE.getValue()))) {
            // 商品不在正常状态，修改失败
            throw new YamiShopBindException("yami.product.on.normal");
        }
        Long shopId = SecurityUtils.getShopUser().getShopId();
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            // 店铺处于违规下线中，不能修改商品，请联系管理员后重试
            throw new YamiShopBindException("yami.product.shop.offline");
        }

        if(Objects.equals(productParam.getStatus(),1)){
            Category category = categoryService.getById(dbProduct.getCategoryId());
            if (category == null || Objects.equals(category.getStatus(), 0)){
                // 平台分类处于下线中，商品不能上架，请联系管理员后再进行操作
                throw new YamiShopBindException("yami.product.category.offline");
            }
            Category shopCategory = categoryService.getById(dbProduct.getShopCategoryId());
            if (shopCategory == null || Objects.equals(shopCategory.getStatus(), 0)){
                // 本店分类处于下线中，商品不能上架
                throw new YamiShopBindException("yami.product.shop.category.offline");
            }
        }

        Product product = new Product();
        product.setProdId(prodId);
        product.setStatus(prodStatus);
        product.setIsTop(0);
        if (prodStatus == 1) {
            product.setPutawayTime(new Date());
        }
        dbProduct.setStatus(prodStatus);
        // 商品状态改变时的发送事件，让活动下线
        applicationContext.publishEvent(new ProdChangeStatusEvent(dbProduct, dbProduct.getStatus()));

        productService.updateById(product);

        // 如果是商品下架操作
        // 此段代码可以用Spring事件监听进行解耦，时间紧迫，以后再算，有待优化。
        if (prodStatus == 0) {
            // 下架时检查是否有拼团活动，有的话使之全部失效
            LambdaQueryWrapper<GroupProd> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper
                    .eq(GroupProd::getShopId, shopId)
                    .eq(GroupProd::getProdId, prodId)
                    .eq(GroupProd::getStatus, 1);
            List<GroupProd> groupProdList = groupProdService.list(lambdaQueryWrapper);
            for (GroupProd groupProd : groupProdList) {
                // 查看团购活动
                ApiGroupActivityDto apiGroupActivityInfo = groupActivityService.getApiGroupActivityInfo(groupProd.getGroupActivityId(), groupProd.getProdId());
                // 当团购活动ID存在且处于进行中的状态时才对拼团商品进行失效处理
                if (Objects.nonNull(apiGroupActivityInfo) && Objects.equals(apiGroupActivityInfo.getActivityStatus(), ActivityStatusEnum.UNDER_WAY.value())) {
                    groupProdService.invalidGroupProd(groupProd);
                }
            }
        }

        productService.removeProdCacheByProdId(prodId,LanguageEnum.LANGUAGE_ZH_CN.getLang());
        productService.removeProdCacheByProdId(prodId,LanguageEnum.LANGUAGE_EN.getLang());
        List<String> userIds = basketService.listUserIdByProdId(prodId);

        for (String userId : userIds) {
            basketService.removeShopCartItemsCacheByUserId(userId,LanguageEnum.LANGUAGE_ZH_CN.getLang());
            basketService.removeShopCartItemsCacheByUserId(userId,LanguageEnum.LANGUAGE_EN.getLang());
        }
        return ResponseEntity.ok().build();
    }

    /**
     * 批量删除
     * @param ids
     * @return 是否删除成功
     */
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('prod:prod:batchDelete')")
    public ResponseEntity<Boolean> batchRemoveById(@RequestBody Long[] ids) {
        // TODO 待优化
        StringBuilder stringBuilder = new StringBuilder();
        for (Long prodId : ids) {
            try {
                delete(prodId);
            } catch (Exception e) {
                Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
                stringBuilder.append("【").append(dbProduct.getProdName()).append("】  ");
            }
        }
        if (stringBuilder.length()>0){
            throw new YamiShopBindException("部分商品删除异常，请刷新页面后手动检查：" + stringBuilder.toString());
        }
        return ResponseEntity.ok().build();
    }

    /**
     * 批量更新商品状态
     * @param ids
     * @param status
     * @return
     */
    @PutMapping("/batchProdStatus/{status}")
    @PreAuthorize("@pms.hasPermission('prod:prod:batchStatus')")
    public ResponseEntity<Void> batchShopStatus(@RequestBody Long[] ids, @PathVariable("status") Integer status) {
        // TODO 待优化
        ProductParam product = new ProductParam();
        product.setStatus(status);
        StringBuilder stringBuilder = new StringBuilder();
        for (Long prodId : ids) {
            product.setProdId(prodId);
            try {
                shopStatus(product);
            } catch (Exception e) {
                Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
                //【商品名】:错误信息xxx (【数码相机】:本店分类处于下线中，商品不能上架)
                stringBuilder.append("【"+dbProduct.getProdName()+"】:"+e.getMessage()+"\n");
            }
        }
        if (stringBuilder.length()>0){
            throw new YamiShopBindException("部分商品状态修改异常，请刷新页面后手动检查：" + stringBuilder.toString());
        }
        return ResponseEntity.ok().build();
    }

    /**
     * 违规商品提交审核
     */
    @PostMapping("/auditApply")
    @PreAuthorize("@pms.hasPermission('prod:prod:audit')")
    public ResponseEntity<Void> auditApply(@RequestBody OfflineHandleEventAuditParam offlineHandleEventAuditParam) {
        Product product = productService.getProductByProdId(offlineHandleEventAuditParam.getHandleId(), I18nMessage.getDbLang());
        if (product == null) {
            // 商品信息不存在
            throw new YamiShopBindException("yami.product.no.exist");
        }
        productService.auditApply(offlineHandleEventAuditParam.getEventId(), offlineHandleEventAuditParam.getHandleId(), offlineHandleEventAuditParam.getReapplyReason());
        // 移除缓存
        productService.removeProdCacheByProdId(product.getProdId(),LanguageEnum.LANGUAGE_ZH_CN.getLang());
        productService.removeProdCacheByProdId(product.getProdId(),LanguageEnum.LANGUAGE_EN.getLang());
        return ResponseEntity.ok().build();
    }

    /**
     * 通过prodId获取最新下线商品的事件
     */
    @GetMapping("/getOfflineHandleEventByProdId/{prodId}")
    public ResponseEntity<OfflineHandleEvent> getByProdId(@PathVariable Long prodId) {
        OfflineHandleEvent offlineHandleEvent = offlineHandleEventService.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.PROD.getValue(), prodId);
        return ResponseEntity.ok(offlineHandleEvent);
    }

    /**
     * 导出商品
     *
     * @param productParam 导出商品筛选条件
     */
    @GetMapping("/exportProd")
    @PreAuthorize("@pms.hasPermission('prod:prod:exportProd')")
    public void exportProd(ProductExportParam productParam, HttpServletResponse response) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        productParam.setShopId(shopId);
        productService.exportProd(productParam,response,shopId);
    }

    @GetMapping(value = "/downloadModel")
    @ResponseBody
    @PreAuthorize("@pms.hasPermission('prod:prod:downloadModel')")
    public ResponseEntity downloadModel(HttpServletResponse response) {

        productService.downloadModel(response,SecurityUtils.getShopUser().getShopId());
        // 开始下载模板
        return ResponseEntity.ok(I18nMessage.getMessage("yami.product.download"));
    }


    @ApiOperation(value = "导入文件")
    @RequestMapping(value = "/exportExcel", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity exportExcel(@RequestParam("excelFile") MultipartFile excelFile) throws Exception {
        if(excelFile == null) {
            // 网络繁忙，请稍后重试
            throw new YamiShopBindException("yami.network.busy");
        }
        Long shopId = SecurityUtils.getShopUser().getShopId();
        return ResponseEntity.ok(productService.parseFile(excelFile,shopId));
    }

    private void checkParam(ProductParam productParam) {

        Product.DeliveryModeVO deliveryMode = productParam.getDeliveryModeVo();
        boolean hasDeliverMode = deliveryMode != null
                && (deliveryMode.getHasShopDelivery() || deliveryMode.getHasUserPickUp() || deliveryMode.getHasCityDelivery());
        if (!hasDeliverMode) {
            // 请选择配送方式
            throw new YamiShopBindException("yami.product.dvy.type");
        }
        Category category = categoryService.getById(productParam.getCategoryId());
        if(category.getGrade() < CategoryLevel.THIRD.value()){
            // 请选择三级分类
            throw new YamiShopBindException("yami.prod.category.error");
        }
        List<Sku> skuList = productParam.getSkuList();
        boolean isAllUnUse = true;
        for (Sku sku : skuList) {
            if (sku.getStatus() == 1) {
                isAllUnUse = false;
            }
        }
        if (isAllUnUse) {
            // 至少要启用一种商品规格
            throw new YamiShopBindException("yami.product.enable.sku");
        }
        if (Objects.equals(1,productParam.getIsCompose())) {
            // 如果是组合商品，必须又一个sku是与单品关联的
            productParam.getSkuList().forEach(i->
                    {
                        if (CollectionUtils.isEmpty(i.getSkuSingleProds())) {
                            // 组合单品必须关联一个单品
                            throw new YamiShopBindException("yami.product.group.check");
                        }
                        for (RetailProdParam skuSingleProd : i.getSkuSingleProds()) {
                            if (skuSingleProd.getRetailNums() <= 0) {
                                throw new YamiShopBindException(i.getSkuName() + skuSingleProd.getName() + I18nMessage.getMessage("yami.retail.prod.compose"));
                            }
                        }
                    }
            );
        }
    }


}
